#!/usr/bin/env bash
. ./wvtest-bup.sh || exit $?

set -o pipefail

top="$(WVPASS pwd)" || exit $?
tmpdir="$(WVPASS wvmktempdir)" || exit $?

bup() { "$top/bup" "$@"; }

WVPASS "$top/dev/sync-tree" "$top/test/sampledata/" "$tmpdir/src/"

export BUP_DIR="$tmpdir/bup"
export GIT_DIR="$tmpdir/bup"

WVPASS bup init
WVPASS cd "$tmpdir"

WVSTART "fsck"

WVPASS bup index src
WVPASS bup save -n fsck-test src/b2
WVPASS bup save -n fsck-test src/var/cmd
WVPASS bup save -n fsck-test src/var/doc
WVPASS bup save -n fsck-test src/var/lib
WVPASS bup save -n fsck-test src/y
WVPASS bup fsck
WVPASS bup fsck "$BUP_DIR"/objects/pack/pack-*.pack
WVPASS bup fsck --quick
if bup fsck --par2-ok; then
    WVSTART "fsck (par2)"
else
    WVSTART "fsck (PAR2 IS MISSING)"
fi
WVPASS bup fsck -g
WVPASS bup fsck -r

WVSTART "fsck (index repairs)"
WVPASS chmod u+w "$BUP_DIR"/objects/pack/*.idx
WVPASS bup damage "$BUP_DIR"/objects/pack/*.idx -n10 -s1 -S0
WVFAIL bup fsck --quick
WVFAIL bup fsck --quick --disable-par2
bup fsck -r
WVPASSEQ 1 $?
if bup fsck --par2-ok; then
    WVPASS chmod u+w "$BUP_DIR"/objects/pack/*.idx
    WVPASS bup damage "$BUP_DIR"/objects/pack/*.idx -n10 -s1 -S0
    bup fsck -r --disable-par2
    WVPASSEQ 2 $?
fi

WVSTART "fsck (pack repairs)"
WVPASS bup damage "$BUP_DIR"/objects/pack/*.pack -n10 -s1 -S0
WVFAIL bup fsck --quick
WVFAIL bup fsck --quick --disable-par2

WVPASS chmod u+w "$BUP_DIR"/objects/pack/*.idx
WVPASS bup damage "$BUP_DIR"/objects/pack/*.idx -n10 -s1 -S0
WVFAIL bup fsck --quick -j4
WVPASS bup damage "$BUP_DIR"/objects/pack/*.pack -n10 -s1024 --percent 0.4 -S0
WVFAIL bup fsck --quick

if ! bup fsck --par2-ok; then
    bup fsck --quick -rvv -j9
    rc=$?
    WVPASSNE 0 "$rc"
    WVPASSNE 1 "$rc"
else
    bup fsck --quick -rvv -j9;
    WVPASSEQ 1 $?

    some_idx="$(WVPASS find "$BUP_DIR" -name "pack-*.par2" \! -name "*.vol*.par2" | head -1)" || exit $?
    some_vol="$(WVPASS find "$BUP_DIR" -name "pack-*.vol*.par2" | head -1)" || exit $?

    WVPASS cp -p "$some_idx" some-pack.par2
    WVPASS cp -p "$some_vol" some-pack.vol.par2

    WVSTART 'fsck rejects empty par2 index files'
    WVPASS echo -n > "$some_idx"
    WVFAIL bup fsck -v
    WVPASS test -e "$some_idx" -a ! -s "$some_idx"
    WVFAIL bup fsck -vr
    WVPASS test -e "$some_idx" -a ! -s "$some_idx"
    WVFAIL bup fsck -vg
    WVPASS test -e "$some_idx" -a ! -s "$some_idx"
    WVPASS cp -p some-pack.par2 "$some_idx"

    WVSTART 'fsck rejects empty par2 vol files'
    WVPASS echo -n > "$some_vol"
    WVFAIL bup fsck -v
    WVPASS test -e "$some_vol" -a ! -s "$some_vol"
    WVFAIL bup fsck -vr
    WVPASS test -e "$some_vol" -a ! -s "$some_vol"
    WVFAIL bup fsck -vg
    WVPASS test -e "$some_vol" -a ! -s "$some_vol"
    WVPASS cp -p some-pack.vol.par2 "$some_vol"

    # This must do "too much" damage.  Currently par2 is invoked with
    # -c200, which should allow up to 200 damaged "blocks", but since
    # we don't specify the block size, it's dynamically computed.
    # Even if we did specify a size, the actual size appears to be
    # affected by the input file sizes, and the specific behavior
    # doesn't appear to be documented/promised -- see par2
    # comandline.cpp.  Also worth noting that bup damage's output is
    # currently probabilistic, so it might not actually damage any
    # given byte.  For now, just try to overdo it -- randomly change
    # (or not 1/256th of the time) 600 evenly spaced bytes in each
    # pack file.
    WVPASS bup damage "$BUP_DIR"/objects/pack/*.pack -n600 -s1 --equal -S0
    WVFAIL bup fsck

    bup fsck -rvv   # too many errors to be repairable
    rc=$?
    WVPASSNE 0 "$rc"
    WVPASSNE 1 "$rc"

    bup fsck -r   # too many errors to be repairable
    rc=$?
    WVPASSNE 0 "$rc"
    WVPASSNE 1 "$rc"
fi


WVPASS cd "$top"
WVPASS rm -rf "$tmpdir"
